/*
 *  CEAnimationFactory.h
 *  LID Library
 *
 *  Created by Alexander Trutchenko on 09/11/11.
 *  Copyright 2011 League of Independent Developers. All rights reserved.
 *
 */

#ifndef __CE_Animation_Factory_h__
#define __CE_Animation_Factory_h__

#include "lid_lib/src/types/LLDataNode.h"

#include <list>
#include <utility>
#include <string>

namespace cocos2d
{
class CCAnimation;
class CCScene;
}


namespace cocosext {

/////////////////////////////////////////////////////
// Defines

// Animation descriptions node name in const data node of data manager
#define kCEAF_animationsNodeName "animations"

//Any animation description has header and body

// Animation descriptions formats
#define kCEAF_AnimationDescriptionKey_Format_FormatString	"format_string"

//Here we have a set of files named by special order. Each of them is a animation frame texture

//Example:
	/** Header of kCEAF_AnimationDescriptionKey_Format_FormatString*/
//<key>format</key>         <string>format_string</string>
//<key>direction</key>      <string>forward_backward</string>
//<key>delay</key>          <real>0.1</real>
	/** Body of kCEAF_AnimationDescriptionKey_Format_FormatString*/
//<key>format</key>         <string>format_string</string>
//<key>texture</key>        <string>tc_fm_move_%03d.png</string>
//<key>start_index</key>    <integer>1</integer>
//<key>frames_count</key>   <integer>18</integer>

#define kCEAF_AnimationDescriptionKey_Format_Normal			"normal"

//Example:
/** Header of kCEAF_AnimationDescriptionKey_Format_Normal*/
//<key>format</key>         <string>normal</string>
//<key>direction</key>      <string>forward</string>
//<key>delay</key>          <real>0.2</real>

/** Body of kCEAF_AnimationDescriptionKey_Format_Normal*/
//<key>frame_width</key>    <integer>84</integer>
//<key>frame_height</key>   <integer>84</integer>
//<sources> 
//  <source>
//      <key>texture</key>          <string>ray_aiming_add.png</string>
//      <key>frames_in_row</key>    <integer>4</integer>
//      <key>frames_count</key>     <integer>8</integer>
//  </source>
//  <source>
//      <key>texture</key>          <string>ray_aiming_end.png</string>
//      <key>frames_in_row</key>    <integer>2</integer>
//      <key>frames_count</key>     <integer>2</integer>
//  </source>
//</sources> 

	/** It is a combination of diffenent formats */
#define kCEAF_AnimationDescriptionKey_Format_Container			"container"
//Example:
/** Header of kCEAF_AnimationDescriptionKey_Format_Container*/
//<key>format</key>         <string>container</string>
//<key>direction</key>      <string>forward</string>
//<key>delay</key>          <real>0.2</real>

/** Body of kCEAF_AnimationDescriptionKey_Format_Normal*/
//<elements> 
//  <element> 
//			/** Short header of kCEAF_AnimationDescriptionKey_Format_Normal*/
//		<key>format</key>         <string>normal</string>
//			/** Body of kCEAF_AnimationDescriptionKey_Format_Normal*/
//		<key>frame_width</key>    <integer>84</integer>
//		<key>frame_height</key>   <integer>84</integer>
//		<sources> 
//		  <source>
//		      <key>texture</key>          <string>ray_aiming_add.png</string>
//		      <key>frames_in_row</key>    <integer>4</integer>
//		      <key>frames_count</key>     <integer>8</integer>
//		  </source>
//		  <source>
//		      <key>texture</key>          <string>ray_aiming_end.png</string>
//		      <key>frames_in_row</key>    <integer>2</integer>
//		      <key>frames_count</key>     <integer>2</integer>
//		  </source>
//		</sources> 
//  </element>
//  <element>
			/** Short header of kCEAF_AnimationDescriptionKey_Format_FormatString*/
//		<key>format</key>         <string>format_string</string>
			/** Body of kCEAF_AnimationDescriptionKey_Format_FormatString*/
//		<key>format</key>         <string>format_string</string>
//		<key>texture</key>        <string>tc_fm_move_%03d.png</string>
//		<key>start_index</key>    <integer>1</integer>
//		<key>frames_count</key>   <integer>18</integer>
//  </element>
//</elements> 


// Animation descriptions format keywords
#define kCEAF_AnimationDescriptionKey_Elements		"elements"
#define kCEAF_AnimationDescriptionKey_Format			"format"
#define kCEAF_AnimationDescriptionKey_Delay			"delay"
#define kCEAF_AnimationDescriptionKey_Sources			"sources"
#define kCEAF_AnimationDescriptionKey_Texture			"texture"
#define kCEAF_AnimationDescriptionKey_StartIndex		"start_index"
#define kCEAF_AnimationDescriptionKey_FramesCount		"frames_count"
#define kCEAF_AnimationDescriptionKey_FramesInRow		"frames_in_row"
#define kCEAF_AnimationDescriptionKey_FrameWidth		"frame_width"
#define kCEAF_AnimationDescriptionKey_FrameHeight		"frame_height"
#define kCEAF_AnimationDescriptionKey_OffsetX			"offset_x"
#define kCEAF_AnimationDescriptionKey_OffsetY			"offset_y"
#define kCEAF_AnimationDescriptionKey_Direction		"direction"
#define kCEAF_AnimationDescriptionKey_Direction_Forward		    "forward"  //default
#define kCEAF_AnimationDescriptionKey_Direction_ForwardBackward	"forward_backward"




/////////////////////////////////////////////////////
//
/** CEAnimationFactory provides additional methods to create animations
 @since v1.1.1
 */
/////////////////////////////////////////////////////

class CEAnimationFactory
{
	typedef std::map<std::string, unsigned int> CEAnimationInfo;
	typedef std::map<cocos2d::CCScene*, std::list<std::string> > CESceneAnimations;

private:
	CEAnimationInfo _allAnimations;
    CESceneAnimations _sceneAnimations;
	cocos2d::CCScene* _currentScene;

private:
    static CEAnimationFactory* _instance;
 
	CEAnimationFactory(): _currentScene(NULL) {};
    ~CEAnimationFactory() {};
     
 
public:
    static CEAnimationFactory* sharedAnimationFactory() 
    {
        if (NULL == _instance) {
                 _instance = new CEAnimationFactory();
        }
        return _instance;
    }

    static void pvt_remove()
    {
        if (NULL != _instance)
            delete _instance;
		_instance = NULL;
    }

public:

    // When we add scene, we can preload animations in connection to this scene
    void onAddScene(cocos2d::CCScene* scene);
	void onReplaceSceneWithTheSameResources(cocos2d::CCScene* oldScene, cocos2d::CCScene* newScene);
    void onRemoveScene(cocos2d::CCScene* scene);
	void setCurrentScene(cocos2d::CCScene* scene);

    //Return preloaded animation
    cocos2d::CCAnimation* getAnimation(const std::string& animationName);
    //Create (if no animation with this name) and return animation 
	cocos2d::CCAnimation* getAnimation(const std::string& animationName, const lidlib::LLDataNodeMap& description);
    //Create animation
    cocos2d::CCAnimation* loadAnimation(const std::string& animationName, const lidlib::LLDataNodeMap& description);
};


/////////////////////////////////////////////////////
//
/** Utility functions
*/
/////////////////////////////////////////////////////

/* Add animation in Normal format */
    /* Add animation header */
extern void addSource(lidlib::LLDataNodeMap* pNm, const char* animationFile, unsigned int framesCount, unsigned int framesInRow, float w = 0.f, float h = 0.f, float offset_x = 0.f, float offset_y = 0.f);
    /* Add animation texture source */
extern void addBeginer(lidlib::LLDataNodeMap& animation, float frameTime, float w, float h);

/* Add animation in String format */
    /* We should have all textures or frames */
extern void addAnimation(lidlib::LLDataNodeMap& animation, const char* textureFormat, const char* direction,  unsigned int startIndex, unsigned int framesCount, float framePeriod);

/* Add animation in Container format */
extern void resetContainer(lidlib::LLDataNodeMap& container, const char* direction, float framePeriod);
extern void addElementToContainer(lidlib::LLDataNodeMap& container, const lidlib::LLDataNodeMap& element);


}; // end namespace cocosext

#endif //__CE_Animation_Factory_h__
